package com.party.orders.service.impl;

import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import com.alipay.api.AlipayApiException;
import com.party.alipay.AlipayRefundDTO;
import com.party.alipay.AlipayRefundVO;
import com.party.alipay.MyAlipayUtils;
import com.party.decoration.mapper.DecorationMapper;
import com.party.domain.Coupon;
import com.party.domain.CurrentAccount;
import com.party.domain.DecorationProduct;
import com.party.domain.Refund;
import com.party.domain.Serve;
import com.party.domain.ShopCart;
import com.party.domain.Site;
import com.party.domain.User;
import com.party.dto.Page;
import com.party.exception.ExceptionMsgEnum;
import com.party.exception.ServiceException;
import com.party.orders.dto.BaseServeProductDTO;
import com.party.orders.dto.BusAmountDTO;
import com.party.orders.dto.CaterAmountDTO;
import com.party.orders.dto.CountAmountDTOBeta;
import com.party.orders.dto.DecorationProductAmountDTO;
import com.party.orders.dto.OrdersDTO;
import com.party.orders.dto.SetMealAmountDTO;
import com.party.orders.dto.ShopCartAmountDTO;
import com.party.orders.dto.SiteAmountDTO;
import com.party.orders.dto.TalentAmountDTO;
import com.party.orders.mapper.CouponMapper;
import com.party.orders.mapper.CouponUserMapper;
import com.party.orders.mapper.CurrentAccountMapper;
import com.party.orders.mapper.RefundMapper;
import com.party.orders.mapper.ShopCartMapper;
import com.party.orders.service.ShopBusinessService;
import com.party.product.mapper.ServeMapper;
import com.party.product.mapper.SiteMapper;
import com.party.tool.OrdersNumUtils;
import com.party.tool.TimeUtils;

/**
 * 
 * @author Caizhf
 * @date 2017年6月13日下午7:28:23
 * @version v.0.1
 * @email 1115054416@qq.com
 *
 *        <p>
 *        Description: 购物这一整块专用的service层：包括清单、订单、支付等等业务
 *        </p>
 *
 */
@Service
public class ShopBusinessServiceImpl implements ShopBusinessService {

	@Autowired
	private ShopCartMapper shopCartMapper;
	@Autowired
	private SiteMapper siteMapper;
	@Autowired
	private ServeMapper serveMapper;
	@Autowired
	private DecorationMapper decMapper;
	@Autowired
	private CurrentAccountMapper currentAccountMapper;
	@Autowired
	private CouponMapper couponMapper;
	@Autowired
	private CouponUserMapper couponUserMapper;
	@Autowired
	private RefundMapper refundMapper;

	private final Logger log = LoggerFactory.getLogger(ShopBusinessServiceImpl.class);

	private static final String TALENT_SERVICE = "达人服务";
	private static final String BUS_SERVICE = "包车服务";
	private static final String CATER_SERVICE = "餐饮服务";
	private static final String SITE = "场地";
	private static final String DEC_PRODUCT = "场地布置";
	private static final String SET_MEAL = "聚会套餐";
	private static final int PRODUCT_NEED_NUM = 1;
	private static final int PAGE_SIZE = 10;

	// 加入清单
	@Override
	@Transactional
	public ShopCart save(ShopCart shopCart) {
		if (StringUtils.isEmpty(shopCart.getProductType()) || shopCart.getProductId() == 0
				|| shopCart.getAdmin().getAid() == 0)
			throw new ServiceException(ExceptionMsgEnum.CLIENT_PARAM_ERROR_MSG);
		shopCart.setOrdersState(SHOP_CART);
		ShopCart sp = shopCartMapper.findByShopCartMsg(shopCart);
		// 如果用户第一次点击添加，就正常save
		if (sp == null) {
			shopCart.setNumber(PRODUCT_NEED_NUM);
			if (shopCartMapper.save(shopCart) == null)
				throw new ServiceException(ExceptionMsgEnum.SERVER_ERROR_MSG);
			return shopCart;
		} else {
			// 如果用户多次点击，那么就修改信息即可
			int newNumber = sp.getNumber() + 1;
			shopCartMapper.updateNumberById(sp.getSpid(), newNumber);
			return sp;
		}
	}

	// 删除清单中的某项
	@Override
	@Transactional
	public void delete(int spid) {
		if (spid == 0)
			throw new ServiceException(ExceptionMsgEnum.CLIENT_PARAM_ERROR_MSG);
		// 如果这个清单的状态不是0，不允许删除
		ShopCart shopCart = shopCartMapper.findById(spid);
		if (shopCart.getOrdersState() != 0)
			throw new ServiceException("这个条例不能删除，它已经不是清单的状态了");
		if (shopCartMapper.deleteById(spid) == null)
			throw new ServiceException(ExceptionMsgEnum.SERVER_DB_NOTEXIT);
	}

	@Override
	@Transactional(propagation = Propagation.REQUIRED, readOnly = true)
	public Map<String, List> listShopCart(int userId) {
		Map<String, List> showPage = new HashMap<String, List>();
		// 查出用户所有加入过清单的场地
		List<OrdersDTO> sites = shopCartMapper.listSiteShopCartByUserIdAndState(userId, SHOP_CART, null, null);
		// 查出用户所有加入过清单的达人服务
		List<OrdersDTO> talents = shopCartMapper.listServeShopCartByUserIdAndStateAndServeType(userId, SHOP_CART,
				TALENT_SERVICE, null, null);
		// 查出用户所有加入过清单的包车服务
		List<OrdersDTO> buses = shopCartMapper.listServeShopCartByUserIdAndStateAndServeType(userId, SHOP_CART,
				BUS_SERVICE, null, null);
		// 查出用户所有加入过清单的餐饮服务
		List<OrdersDTO> caters = shopCartMapper.listServeShopCartByUserIdAndStateAndServeType(userId, SHOP_CART,
				CATER_SERVICE, null, null);
		// 查出用户所有加入过清单的场地布置商品
		List<OrdersDTO> decorationProducts = shopCartMapper.listDecProductShopCartByUserIdAndState(userId, SHOP_CART,
				null, null);
		// 查出用户所有加入过清单的套餐
		List<OrdersDTO> setMeals = shopCartMapper.listSetMealShopCartByUserIdAndState(userId, SHOP_CART, null, null);

		showPage.put(SITE, sites);
		showPage.put(DEC_PRODUCT, decorationProducts);
		showPage.put(CATER_SERVICE, caters);
		showPage.put(TALENT_SERVICE, talents);
		showPage.put(BUS_SERVICE, buses);
		showPage.put(SET_MEAL, setMeals);

		return showPage;
	}

	@Override
	@Transactional(readOnly = true)
	public Map<String, List> listOrders(int userId, int ordersState, int pageNum, int pageSize) {
		if (ordersState < 1)
			throw new ServiceException("不是订单状态!");
		int totleRecord = shopCartMapper.countByStateAndUserId(userId, ordersState);
		Page page = null;
		if (pageNum == 0)
			page = new Page(totleRecord, 1);
		else
			// 如果不为空，那么就按照想看的页码进行
			page = new Page(totleRecord, pageNum, pageSize);

		Map<String, List> showPage = new HashMap<String, List>();
		// 查出用户所有加入过清单的场地
		List<OrdersDTO> sites = shopCartMapper.listSiteShopCartByUserIdAndState(userId, ordersState,
				page.getStartindex(), pageSize);
		// 查出用户所有加入过清单的达人服务
		List<OrdersDTO> talents = shopCartMapper.listServeShopCartByUserIdAndStateAndServeType(userId, ordersState,
				TALENT_SERVICE, page.getStartindex(), pageSize);
		// 查出用户所有加入过清单的包车服务
		List<OrdersDTO> buses = shopCartMapper.listServeShopCartByUserIdAndStateAndServeType(userId, ordersState,
				BUS_SERVICE, page.getStartindex(), pageSize);
		// 查出用户所有加入过清单的餐饮服务
		List<OrdersDTO> caters = shopCartMapper.listServeShopCartByUserIdAndStateAndServeType(userId, ordersState,
				CATER_SERVICE, page.getStartindex(), pageSize);
		//// 查出用户所有加入过清单的场地布置商品
		List<OrdersDTO> decorationProducts = shopCartMapper.listDecProductShopCartByUserIdAndState(userId, ordersState,
				page.getStartindex(), pageSize);
		// 查出用户所有加入过清单的套餐
		List<OrdersDTO> setMeals = shopCartMapper.listSetMealShopCartByUserIdAndState(userId, ordersState,
				page.getStartindex(), pageSize);

		showPage.put(SITE, sites);
		showPage.put(DEC_PRODUCT, decorationProducts);
		showPage.put(CATER_SERVICE, caters);
		showPage.put(TALENT_SERVICE, talents);
		showPage.put(BUS_SERVICE, buses);
		showPage.put(SET_MEAL, setMeals);

		return showPage;
	}

	@Override
	public OrdersDTO findById(int spid) {
		if (spid == 0)
			throw new ServiceException(ExceptionMsgEnum.CLIENT_PARAM_ERROR_MSG);
		OrdersDTO orders = shopCartMapper.findById(spid);
		if (orders == null)
			throw new ServiceException(ExceptionMsgEnum.SERVER_DB_NOTEXIT);

		if (orders.getProductType().equals(SITE)) {
			// 如果是场地
			orders.setProduct(siteMapper.findByIdSite(orders.getProductId()));
		} else if (orders.getProductType().equals("布置商品")) {
			// 如果是场地布置下的商品
			orders.setProduct(decMapper.findByProductId(orders.getProductId()));
		} else {
			// 不然就是二级服务了
			orders.setProduct(serveMapper.findById(orders.getProductId()));
		}
		
		//如果该订单是预约中（已支付，待处理）的状态、并且是已经有付款金额的状态，
		//那么就拿当前系统时间与付款的时间对比,如果超过了6个小时，那么就直接退款,并且修改状态,增加退款原因
		int status = orders.getOrdersState();
		Double payMoney = orders.getActualPay();
		//将当前时间与下单支付时间对比
		CurrentAccount ca = currentAccountMapper.findByShopCartId(spid);
		int difftimeHours = 0;
		if(ca!=null){
			difftimeHours = TimeUtils.getDifftimeHours(ca.getGmtPayment(), new Date(System.currentTimeMillis()));
		}
		if(status==PEND && payMoney!=0 && difftimeHours >= 6){
			final String refundReason = "商家超过6个小时未接单，自动退款";
			try {
				//执行自动退款请求
				AlipayRefundVO refundVO = MyAlipayUtils.refund(ca.getAllOrderNum(), ca.getTradeNo(), null, payMoney.toString(), refundReason);
				AlipayRefundDTO refundDTO = refundVO.getAlipay_trade_refund_response();
				if(refundDTO.getCode().equals("10000")){
					//存储退款状态
					refundMapper.save(new Refund(new Date(System.currentTimeMillis()),new Date(System.currentTimeMillis()),
							payMoney,refundReason,null,refundDTO.getBuyer_logon_id(),orders));
					//修改清单状态为已经退款
					shopCartMapper.updateStateById(REFUNDED, spid);
				}else{
					//支付宝接口调用退款失败（非程序异常原因失败导致出现的问题）
					// 退款失败原因与状态码
					String failueReason = "支付宝调用问题：" + "\n错误代码：" + refundDTO.getCode() + "\n错误描述："
							+ refundDTO.getMsg() + "\n详情错误码：" + refundDTO.getSub_code() + "\n详情错误信息"
							+ refundDTO.getSub_msg();
					refundMapper.save(new Refund(new Date(System.currentTimeMillis()),new Date(System.currentTimeMillis()),
							payMoney,refundReason,null,null,failueReason,orders));
					//修改为失败状态
					shopCartMapper.updateStateById(REFUND_FAILURED, spid);
				}
			} catch (AlipayApiException e) {
				e.printStackTrace();
				throw new ServiceException("支付宝出现未知错误");
			}
		}
		
		
		
		return orders;
	}

	@Override
	public void updateOnState(int state, int spid) {
		if (spid == 0)
			throw new ServiceException(ExceptionMsgEnum.CLIENT_PARAM_ERROR_MSG);
		shopCartMapper.updateStateById(state, spid);
	}

	// 修改商品所需数量
	@Override
	public void updateNumberBySpid(int spid, int number) {
		shopCartMapper.updateNumberBySpid(spid, number);
	}

	// 取消订单
	@Override
	public void updateOnStateToCanceled(int spid) {
		shopCartMapper.updateStateById(CANCELED, spid);
	}

	// 批处理
	@Override
	@Transactional(propagation = Propagation.REQUIRED)
	public void updateNumbersBySpids(int[] spids, int[] numbers) {
		if (spids == null || numbers == null || spids.length != numbers.length)
			throw new ServiceException(ExceptionMsgEnum.CLIENT_PARAM_ERROR_MSG);
		for (int i = 0; i < spids.length; i++) {
			if (shopCartMapper.updateNumberBySpid(spids[i], numbers[i]) == null)
				throw new ServiceException(ExceptionMsgEnum.SERVER_ERROR_MSG);
		}
	}

	// 场地布置下的商品下单
	@Override
	@Transactional(propagation = Propagation.REQUIRED)
	public void saveOnDecorationProduct(int userId, int[] dpids, int[] numbers, int adminId) {
		if (dpids == null || numbers == null || adminId == 0 || dpids.length != numbers.length)
			throw new ServiceException(ExceptionMsgEnum.CLIENT_PARAM_ERROR_MSG);
		for (int i = 0; i < dpids.length; i++) {
			if (shopCartMapper.saveOnDecorationProduct(userId, dpids[i], numbers[i], adminId, SHOP_CART) == null)
				throw new ServiceException(ExceptionMsgEnum.SERVER_ERROR_MSG);
		}
	}

	// 结算支付业务接口
	/**
	 * 注意事项：由于订单部分的数据库设计问题，需要定时清理无状态的流水账 sql效率：良好
	 * 算法效率：较差（一个方法将近运行10《sql《20次以上，有待优化） 功能测试：能够满足需求
	 */
	@Override
	// @Transactional(propagation=Propagation.REQUIRED)事务在Controller控制
	public CurrentAccount doPay(Integer[] spids, Integer[] cpids, int payWay, User user, Integer allPriceCouponId,
			String activityTime, String contactPhone, String contactUser, String contactNotes) {

		// --------------------清单与流水账的爱恨纠缠--------------//
		if (spids == null || spids.length == 0)
			throw new ServiceException(ExceptionMsgEnum.CLIENT_PARAM_ERROR_MSG);
		// 查询spids中的所有清单
		List<ShopCart> shopCarts = shopCartMapper.findByIds(spids);
		// 把在该数组内的清单状态全部设置为未支付（status=1），设置好联系人等信息
		if (shopCartMapper.updateStateByIds(UNPAY, spids, activityTime, contactPhone, contactUser,
				contactNotes) == null)
			throw new ServiceException(ExceptionMsgEnum.SERVER_ERROR_MSG);

		// 生成一个流水账对象，并且插入除了支付宝交易单号、金额以外的所有属性；将清单与流水账级联
		int status = CurrentAccount.UN_PAY;// 未支付
		CurrentAccount ca = new CurrentAccount(null, OrdersNumUtils.getOrdersNum(), new Date(), null, payWay, null,
				CurrentAccount.SUBJECT, status, user);

		if (currentAccountMapper.save(ca) == null)
			throw new ServiceException(ExceptionMsgEnum.SERVER_ERROR_MSG);

		// 级联清单与订单
		if (shopCartMapper.updateForeignKeyCurrentAccountByIds(spids, ca.getCaid()) == null)
			throw new ServiceException(ExceptionMsgEnum.SERVER_ERROR_MSG);

		// ------------------根据清单列表计算总价格-------------------//
		// 该返回对象是专门记录各个产品详细价格信息的
		CountAmountDTOBeta amountDTOBeta = getTotalAmountByShopCarts(shopCarts);

		// ------------------------计算优惠券总价----------------------//
		// 根据优惠券列表计算减价
		if (cpids != null && cpids.length != 0) {
			// 查询该优惠券id数组中的所有优惠券
			List<Coupon> coupons = couponMapper.listByIds(cpids);
			// 判断这些优惠券是否是当前session用户所领取的（检测非法传入）

			// 判断这些优惠券是否是还在期限内能使用的

			// 计算优惠券减掉的总金额数目，当amountDTO调用getTotalAmount方法的时候会自己减掉这部分的价格
			amountDTOBeta = getCouponTotalAmountReduce(coupons, amountDTOBeta, user.getId(), null);
		} // 如果该优惠券是总单满减的类型
		else if (allPriceCouponId != null) {
			Coupon allPriceCoupon = couponMapper.findById(allPriceCouponId);
			amountDTOBeta = getCouponTotalAmountReduce(null, amountDTOBeta, user.getId(), allPriceCoupon);
		}

		// 计算单个订单的价格并插入数据库
		doUpdateOneShopCartPrice(amountDTOBeta);
		log.info("------------------------------》计算单个订单价格实际付款后状态" + amountDTOBeta.toString());
		// 计算最终价格(减去优惠券)
		ca.setTotalAmount(amountDTOBeta.getTotalactualPay());
		log.info("------------------------------》最终状态" + amountDTOBeta.toString());
		return ca;
	}

	// 计算总价的算法
	private CountAmountDTOBeta getTotalAmountByShopCarts(List<ShopCart> shopCarts) {
		log.info("------------------------------》已经进入计算总价算法");
		double totalAmount = 0.00;
		CountAmountDTOBeta amountDTOBeta = new CountAmountDTOBeta();
		log.info("------------------------------》目前对象状态" + amountDTOBeta.toString());
		for (ShopCart sc : shopCarts) {
			int productId = sc.getProductId();
			String productType = sc.getProductType();
			double price = 0.00;
			BaseServeProductDTO productPriceDTO = null;
			// 如果今天是周末,并且产品是场地
			if (OrdersNumUtils.isWeekend(Calendar.getInstance()) && productType.equals(SITE)) {
				// 取出场地周末价格
				Site site = siteMapper.findByIdSite(productId);
				if (null != site.getWeekPrice())
					price = site.getWeekPrice();
				else
					price = site.getPrice();
			} else {
				// 如果不是周末，就按照平常价格
				productPriceDTO = shopCartMapper.findProductPriceByProductIdAndProductType(productId, productType);
				price = productPriceDTO.getPrice();
			}

			// 还需要计算产品所需数量才得到最终某个产品的总价
			price *= sc.getNumber();
			// 在DTO中记录状态，可以计算出各个类型产品的总价详情
			if (productType.equals("场地")) {
				SiteAmountDTO siteAmount = amountDTOBeta.getSiteAmount();
				siteAmount.getShopCarts().add(new ShopCartAmountDTO(sc, price));
				siteAmount.addTotalAmount(price);

			} else if (productType.equals("二级服务") && (!StringUtils.isEmpty(productPriceDTO.getServeType()))) {
				if (productPriceDTO.getServeType().equals("达人服务")) {
					TalentAmountDTO talentAmount = amountDTOBeta.getTalentAmount();
					talentAmount.getShopCarts().add(new ShopCartAmountDTO(sc, price));
					talentAmount.addTotalAmount(price);
				} else if (productPriceDTO.getServeType().equals("餐饮服务")) {
					CaterAmountDTO caterAmount = amountDTOBeta.getCaterAmount();
					caterAmount.getShopCarts().add(new ShopCartAmountDTO(sc, price));
					caterAmount.addTotalAmount(price);
				} else if (productPriceDTO.getServeType().equals("包车服务")) {
					BusAmountDTO busAmount = amountDTOBeta.getBusAmount();
					busAmount.getShopCarts().add(new ShopCartAmountDTO(sc, price));
					busAmount.addTotalAmount(price);
				}
			} else if (productType.equals("布置商品")) {
				DecorationProductAmountDTO decProductAmount = amountDTOBeta.getDecProductAmount();
				decProductAmount.getShopCarts().add(new ShopCartAmountDTO(sc, price));
				decProductAmount.addTotalAmount(price);
			} else if (productType.equals("聚会套餐")) {
				SetMealAmountDTO setMealAmount = amountDTOBeta.getSetMealAmount();
				setMealAmount.getShopCarts().add(new ShopCartAmountDTO(sc, price));
				setMealAmount.addTotalAmount(price);
			}
			// 累加最终总价
			totalAmount += price;
		}
		// 设置总金额
		amountDTOBeta.setTotalAmount(totalAmount);
		log.info("------------------------------》结束后对象状态" + amountDTOBeta.toString());
		return amountDTOBeta;
	}

	// 计算优惠券减价的算法
	private CountAmountDTOBeta getCouponTotalAmountReduce(List<Coupon> coupons, CountAmountDTOBeta amountDTOBeta,
			int userId, Coupon allPriceCoupon) {
		log.info("------------------------------》优惠券算法开始");
		final int USED = 1;
		// 如果该优惠券是总单满减的类型,并且除去套餐价格后还满足优惠金额的(因为套餐不能算在总价满减中)
		if (coupons == null && allPriceCoupon != null
				&& allPriceCoupon.getAmountNeed() <= (amountDTOBeta.getTotalAmount()
						- amountDTOBeta.getSetMealAmount().getTotalAmount())) {
			// 如果满足，那么就在总价执行优惠券减价
			amountDTOBeta.addCouponAmount(allPriceCoupon.getFavourablePrice());
			//设置状态为总价类型
			amountDTOBeta.setAllCouponReduce(true);
			// 状态设置为该用户已经用过
			couponUserMapper.updateStatusByUserIdAndCpid(userId, allPriceCoupon.getCpid(), USED);
		}
		// 如果该优惠券是分散商品使用的
		else if (coupons != null && coupons.size() != 0) {
			// 遍历检测数组中的优惠券产品类型（假设为场地），就去查询相应产品（场地）的价格
			for (Coupon coupon : coupons) {
				// 满减所需金额
				double couponAmountNeed = coupon.getAmountNeed();
				// 优惠产品类型
				int productType = coupon.getProductType();
				// 满减减掉的金额
				double favourablePrice = coupon.getFavourablePrice();
				// 判断选购的产品（0场地，1布置商品，2达人服务，3包车服务，4餐饮服务，5套餐）（注意数量）价格是否达到优惠券的满减条件
				if ((productType == 0 && (couponAmountNeed <= amountDTOBeta.getSiteAmount().getTotalAmount()))) {
					SiteAmountDTO siteAmount = amountDTOBeta.getSiteAmount();
					// 如果满足，那么就在总价执行优惠券减价
					siteAmount.addCouponTotalReduce(favourablePrice);
					amountDTOBeta.addCouponAmount(favourablePrice);
					// 状态设置为该用户已经用过
					couponUserMapper.updateStatusByUserIdAndCpid(userId, coupon.getCpid(), USED);
				} else if ((productType == 1
						&& (couponAmountNeed <= amountDTOBeta.getDecProductAmount().getTotalAmount()))) {
					DecorationProductAmountDTO decProductAmount = amountDTOBeta.getDecProductAmount();
					decProductAmount.addCouponTotalReduce(favourablePrice);
					amountDTOBeta.addCouponAmount(favourablePrice);
					couponUserMapper.updateStatusByUserIdAndCpid(userId, coupon.getCpid(), USED);
				} else if ((productType == 2
						&& (couponAmountNeed <= amountDTOBeta.getTalentAmount().getTotalAmount()))) {
					TalentAmountDTO talentAmount = amountDTOBeta.getTalentAmount();
					talentAmount.addCouponTotalReduce(favourablePrice);
					amountDTOBeta.addCouponAmount(favourablePrice);
					couponUserMapper.updateStatusByUserIdAndCpid(userId, coupon.getCpid(), USED);
				} else if ((productType == 3 && (couponAmountNeed <= amountDTOBeta.getBusAmount().getTotalAmount()))) {
					BusAmountDTO busAmount = amountDTOBeta.getBusAmount();
					busAmount.addCouponTotalReduce(favourablePrice);
					amountDTOBeta.addCouponAmount(favourablePrice);
					couponUserMapper.updateStatusByUserIdAndCpid(userId, coupon.getCpid(), USED);
				} else if ((productType == 4
						&& (couponAmountNeed <= amountDTOBeta.getCaterAmount().getTotalAmount()))) {
					CaterAmountDTO caterAmount = amountDTOBeta.getCaterAmount();
					caterAmount.addCouponTotalReduce(favourablePrice);
					amountDTOBeta.addCouponAmount(favourablePrice);
					couponUserMapper.updateStatusByUserIdAndCpid(userId, coupon.getCpid(), USED);
				} else if ((productType == 5
						&& (couponAmountNeed <= amountDTOBeta.getSetMealAmount().getTotalAmount()))) {
					SetMealAmountDTO setMealAmount = amountDTOBeta.getSetMealAmount();
					setMealAmount.addCouponTotalReduce(favourablePrice);
					amountDTOBeta.addCouponAmount(favourablePrice);
					couponUserMapper.updateStatusByUserIdAndCpid(userId, coupon.getCpid(), USED);
				}
			}
		}
		log.info("------------------------------》优惠券算法结束后目前对象状态" + amountDTOBeta.toString());
		return amountDTOBeta;
	}

	//为退款做准备，所以要计算出每个清单的实际付款情况
	private void doUpdateOneShopCartPrice(CountAmountDTOBeta amountDTOBeta) {
		// 计算单个产品（单个订单）的实际付款，并且插入数据库
		SiteAmountDTO siteAmount = amountDTOBeta.getSiteAmount();
		List<ShopCartAmountDTO> siteShopCarts = siteAmount.getShopCarts();
		if (null != siteShopCarts && siteShopCarts.size() != 0) {
			for (ShopCartAmountDTO scad : siteShopCarts) {
				double shopCartActualPay = 0;
				//如果不是总减劵
				// 得到单给订单的实际付款
				if(!amountDTOBeta.isAllCouponReduce())
					shopCartActualPay = scad.doActualPay(siteAmount.getTotalAmount(), siteAmount.getActualPay());
				else
					shopCartActualPay = scad.doActualPayByAll(amountDTOBeta.getTotalAmount(),amountDTOBeta.getTotalactualPay());
				// 插入数据库
				shopCartMapper.updateActualPayById(scad.getShopCart().getSpid(), shopCartActualPay);
			}
		}
		TalentAmountDTO talentAmount = amountDTOBeta.getTalentAmount();
		List<ShopCartAmountDTO> talentShopCarts = talentAmount.getShopCarts();
		if (null != talentShopCarts && talentShopCarts.size() != 0) {
			for (ShopCartAmountDTO scad : talentShopCarts) {
				double shopCartActualPay = 0;
				//如果不是总减劵
				// 得到单给订单的实际付款
				if(!amountDTOBeta.isAllCouponReduce())
					shopCartActualPay = scad.doActualPay(talentAmount.getTotalAmount(), talentAmount.getActualPay());
				else
					shopCartActualPay = scad.doActualPayByAll(amountDTOBeta.getTotalAmount(),amountDTOBeta.getTotalactualPay());
				// 插入数据库
				shopCartMapper.updateActualPayById(scad.getShopCart().getSpid(), shopCartActualPay);
			}
		}
		CaterAmountDTO caterAmount = amountDTOBeta.getCaterAmount();
		List<ShopCartAmountDTO> caterShopCarts = caterAmount.getShopCarts();
		if (null != caterShopCarts && caterShopCarts.size() != 0) {
			for (ShopCartAmountDTO scad : caterShopCarts) {
				double shopCartActualPay = 0;
				// 得到单给订单的实际付款
				//如果不是总减劵
				if(!amountDTOBeta.isAllCouponReduce())
					shopCartActualPay = scad.doActualPay(caterAmount.getTotalAmount(), caterAmount.getActualPay());
				else
					shopCartActualPay = scad.doActualPayByAll(amountDTOBeta.getTotalAmount(),amountDTOBeta.getTotalactualPay());
				// 插入数据库
				shopCartMapper.updateActualPayById(scad.getShopCart().getSpid(), shopCartActualPay);
			}
		}
		BusAmountDTO busAmount = amountDTOBeta.getBusAmount();
		List<ShopCartAmountDTO> busShopCarts = busAmount.getShopCarts();
		if (null != busShopCarts && busShopCarts.size() != 0) {
			for (ShopCartAmountDTO scad : busShopCarts) {
				double shopCartActualPay = 0;
				// 得到单给订单的实际付款
				//如果不是总减劵
				if(!amountDTOBeta.isAllCouponReduce())
					shopCartActualPay = scad.doActualPay(busAmount.getTotalAmount(), busAmount.getActualPay());
				else
					shopCartActualPay = scad.doActualPayByAll(amountDTOBeta.getTotalAmount(),amountDTOBeta.getTotalactualPay());
				// 插入数据库
				shopCartMapper.updateActualPayById(scad.getShopCart().getSpid(), shopCartActualPay);
			}
		}
		DecorationProductAmountDTO decProductAmount = amountDTOBeta.getDecProductAmount();
		List<ShopCartAmountDTO> decProductShopCarts = decProductAmount.getShopCarts();
		if (null != decProductShopCarts && decProductShopCarts.size() != 0) {
			for (ShopCartAmountDTO scad : decProductShopCarts) {
				double shopCartActualPay = 0;
				// 得到单给订单的实际付款
				//如果不是总减劵
				if(!amountDTOBeta.isAllCouponReduce())
					shopCartActualPay = scad.doActualPay(decProductAmount.getTotalAmount(),
						decProductAmount.getActualPay());
				else
					shopCartActualPay = scad.doActualPayByAll(amountDTOBeta.getTotalAmount(),amountDTOBeta.getTotalactualPay());
				// 插入数据库
				shopCartMapper.updateActualPayById(scad.getShopCart().getSpid(), shopCartActualPay);
			}
		}

		SetMealAmountDTO setMealAmount = amountDTOBeta.getSetMealAmount();
		List<ShopCartAmountDTO> setMealShopCarts = setMealAmount.getShopCarts();
		if (null != setMealShopCarts && setMealShopCarts.size() != 0) {
			for (ShopCartAmountDTO scad : setMealShopCarts) {
				double shopCartActualPay = 0;
				// 得到单给订单的实际付款
				//如果不是总减劵
				if(!amountDTOBeta.isAllCouponReduce())
					shopCartActualPay = scad.doActualPay(setMealAmount.getTotalAmount(),
						setMealAmount.getActualPay());
				else
					shopCartActualPay = scad.doActualPayByAll(amountDTOBeta.getTotalAmount(),amountDTOBeta.getTotalactualPay());
				// 插入数据库
				shopCartMapper.updateActualPayById(scad.getShopCart().getSpid(), shopCartActualPay);
			}
		}
	}

	// 根据状态判断此订单是否是已经处理支付过的
	@Override
	public boolean findCurrentAccountStateByAllOrdersNum(String out_trade_no) {
		boolean status = false;
		// 判断订单是已经支付处理过的状态
		CurrentAccount ca = currentAccountMapper.findByallOrdersNum(out_trade_no);
		if (ca == null)
			throw new ServiceException(ExceptionMsgEnum.SERVER_DB_NOTEXIT);
		if (ca.getStatus() != CurrentAccount.UN_PAY)
			status = true;
		return status;
	}

	// 支付宝支付成功所需要处理的逻辑
	@Override
	@Transactional
	public void doPaySuccess(String out_trade_no, String trade_no, String buyer_logon_id, Date gmt_payment,
			double total_amount) {
		if (StringUtils.isEmpty(trade_no) || StringUtils.isEmpty(out_trade_no) || StringUtils.isEmpty(buyer_logon_id)
				|| gmt_payment == null || total_amount == 0)
			throw new ServiceException("支付宝传入参数出错");

		CurrentAccount ca = currentAccountMapper.findByallOrdersNum(out_trade_no);
		if (ca == null)
			throw new ServiceException(ExceptionMsgEnum.SERVER_DB_NOTEXIT);

		// 更新流水账状态
		ca.setTradeNo(trade_no); // 设置支付宝下单号码
		ca.setBuyerLogonId(buyer_logon_id); // 设置支付宝支付账户
		ca.setGmtPayment(gmt_payment); // 设置支付时间
		ca.setTotalAmount(total_amount); // 设置支付的钱数
		ca.setStatus(CurrentAccount.PAY_SUCCESS);// 设置成已经支付的状态
		currentAccountMapper.updateById(ca);
		// 查询出所有在当前流水账下的清单
		List<ShopCart> shopCartList = shopCartMapper.listByCurrentAccountId(ca.getCaid());
		// 为这些清单完善信息（只要信息完善了就相当于已经正常下单了）
		for (ShopCart sc : shopCartList) {
			// 设置时间
			sc.setCtime(new Date());
			// 生成订单号
			sc.setOrdersNum(OrdersNumUtils.getOrdersNum());

			// 如果支付成功并且没有预约的项目,就把用户那条相应的清单状态修改成3
			if (!sc.getProductType().equals(SITE)) {
				sc.setOrdersState(UNUSED);
				shopCartMapper.updateStateAndNumAndTimeById(sc);
			} else {
				// 如果支付成功并且有预约的项目，就把那条相应的清单状态改成2
				sc.setOrdersState(PEND);
				shopCartMapper.updateStateAndNumAndTimeById(sc);
			}
		}
	}

	@Override
	public void updateCurrentAccountStateOnFinished(String out_trade_no) {
		currentAccountMapper.updateStateByAllOrderNum(out_trade_no, CurrentAccount.PAY_FINISHED);
	}

	@Override
	public List<String> findShopCartByCurrentAccountAllOrderNum(String out_trade_no) {
		// 拿到电话列表
		List<String> list = shopCartMapper.listAdminPhoneNumbersByCurrentAccountAllOrdersNum(out_trade_no);
		return list;
	}

	
	@Override
	@Transactional(propagation=Propagation.REQUIRED)
	public String doRefundRequestExecute(int spid, String refundReason) {
		OrdersDTO spc = shopCartMapper.findById(spid);
		if(null==spc||null==spc.getActualPay())
			throw new ServiceException("请勿传入非法退款请求");
		//加产品价格百分比的时候在这里加,需要在数据库中查出产品退款百分比
		Double refundRate = shopCartMapper.findRefundRateByProductTypeAndProductId(spc.getProductId(),spc.getProductType());
		//如果为空或者是订单已经被取消了，那么就直接原价退款返还
		if(refundRate==null||spc.getOrdersState()==CANCELED)
			refundRate = 1.0;
		//存储有效信息
		Refund rf = new Refund(spc.getActualPay() * refundRate/*实际付款乘以比例*/, refundReason,
				new Date(System.currentTimeMillis()),OrdersNumUtils.getRefundNum(),spc);
		if(refundMapper.save(rf)==null)
			throw new ServiceException(ExceptionMsgEnum.SERVER_ERROR_MSG);
		//修改清单状态为正在退款中，等待商家确认退款信息
		if(shopCartMapper.updateStateById(REFUNDING, spid)==null)
			throw new ServiceException(ExceptionMsgEnum.SERVER_ERROR_MSG);
		
		return spc.getAdmin().getPhoneNumber();
	}

}
